<?php
/**
 *+------------------
 * Lflow
 *+------------------
 * Copyright (c) 2023~2030 gitee.com/liu_guan_qing All rights reserved.本版权不可删除，侵权必究
 *+------------------
 * Author: Mr.April(405784684@qq.com)
 *+------------------
 */
declare (strict_types=1);

namespace lflow\handlers\impl;

use lflow\ckpt\SubProcessCkpt;
use lflow\ckpt\TaskCkpt;
use lflow\core\Execution;
use lflow\handlers\IHandler;

/**
 * 合并处理的抽象处理器
 * 需要子类提供查询无法合并的task集合的参数map
 *
 * @author Mr.April
 * @since  1.0
 */
abstract class AbstractMergeHandler implements IHandler
{

    /**
     * @throws \ReflectionException
     */
    public function handle(Execution $execution): void
    {

        /**
         * 查询当前流程实例的无法参与合并的node列表
         * 若所有中间node都完成，则设置为已合并状态，告诉Ckpt可继续执行join的输出变迁
         */
        $queryService       = $execution->getEngine()->query();
        $order              = $execution->getOrder();
        $ckpt               = $execution->getCkpt();
        $activeNodes        = $this->findActiveNodes();
        $isSubProcessMerged = false;
        $isTaskMerged       = false;

        if ($ckpt->containsNodeNames(SubProcessCkpt::class, $activeNodes)) {
            $where  = [
                'parent_id' => $order->getData('id'),
                'id'        => $execution->getChildOrderId(),
            ];
            $orders = $queryService->getActiveOrder($where);
            if (empty($orders)) {
                $isTaskMerged = true;
            }
        } else {
            $isSubProcessMerged = true;
        }
        if ($isSubProcessMerged && $ckpt->containsNodeNames(TaskCkpt::class, $activeNodes)) {
            $where = [
                'order_id'  => $order->getData('id'),
//                'ids'       => $execution->getTask()->getData('id'),
                'task_name' => $activeNodes,
            ];
            $tasks = $queryService->getActiveTasks($where)['list'];
            if (empty($tasks->toArray())) {
                //如果所有task都已完成，则表示可合并
                $isTaskMerged = true;
            }
        }
        $execution->setMerged($isSubProcessMerged && $isTaskMerged);
    }

    /**
     * 子类需要提供如何查询未合并任务的参数map
     *
     * @return mixed
     */
    protected abstract function findActiveNodes():mixed;
}
